/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package multimedia;

import MVC.IController;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.UnsupportedAudioFileException;

/**
 *
 * @author thomas
 */
public class AudioPlaylistController implements IController {

    private AudioPlaylistModel _myModel;
    private IAudioSongController _myActiveSong;
    private ArrayList<IAudioSongController> _mySongs;
    
    private boolean _isShuffle;
    private boolean _isRepeat;
    
    private int _indexSong;
    private ArrayList<Integer> _myOrder;

    public AudioPlaylistController() {

        _myModel = new AudioPlaylistModel();
        _myActiveSong = null;
        _mySongs = new ArrayList<IAudioSongController>();

        _isShuffle = false;
        _isRepeat = false;

        _indexSong = 0;
        _myOrder = new ArrayList<Integer>();
    }
    
    public void setIndex(int index) {
        _indexSong = index;
        
        _myModel.setCurrentIndex(_myOrder.get(index));
    }
    
    public void changeIndex(int index) {
        setIndex(_indexSong + index);
    }

    /**
     * @return the _myModel
     */
    public AudioPlaylistModel getModel() {
        return _myModel;
    }

    /**
     * Get all songs models
     * @return 
     */
    public ArrayList<AudioSongModel> getModels() {
        ArrayList<AudioSongModel> models = new ArrayList<AudioSongModel>();

        for (IAudioSongController song : _mySongs) {
            models.add(song.getModel());
        }

        return models;
    }

    public IAudioSongController getActiveSongController() {
        return _myActiveSong;
    }

    /**
     * Get all controller songs
     * @return the _mySongs
     */
    public ArrayList<IAudioSongController> getSongs() {
        return _mySongs;
    }

    /**
     * Set a new playlist
     * @param songs the _mySongs to set
     */
    public void setSongs(ArrayList<IAudioSongController> songs) {
        _mySongs = songs;
        for (int i = 0; i < songs.size(); i++) {
            _myOrder.add(i);
        }

        if (_isShuffle) {
            Collections.shuffle(_myOrder);
        }
    }

    public IAudioSongController createSong(String path) throws FileNotFoundException, IOException, UnsupportedAudioFileException {
        IAudioSongController song = new AudioSongController(path, this);        
        return song;
    }
    
    /**
     * Add a song to the playlist
     * @param song the song to add
     */
    public void addSong(IAudioSongController song) {
        _mySongs.add(song);
        _myOrder.add(_mySongs.size() - 1);
        _myModel.addSong(song.getModel());
    }

    /**
     * Create a song thanks to path and add it to the playlist
     * @param path the path to the string to add
     * @throws FileNotFoundException            If file is not found
     * @throws IOException                      If error when file is reading
     * @throws UnsupportedAudioFileException    If extension is not supported by reader
     */
    public void addSong(String path) throws FileNotFoundException, IOException, UnsupportedAudioFileException {
        addSong(createSong(path));
    }

    /**
     * Add a song to the playlist and listen it
     * @param song the song to add
     */
    public void addAndListenToSong(IAudioSongController song) {
        
        stop();
        
        addSong(song);
        _myActiveSong = song;
        
        setIndex(_mySongs.indexOf(song));
        
        play();
    }

    /**
     * Create a song thanks to path, add it to the playlist and listen it
     * @param path the path to the string to add
     * @throws FileNotFoundException            If file is not found
     * @throws IOException                      If error when file is reading
     * @throws UnsupportedAudioFileException    If extension is not supported by reader
     */
    public void addAndListenToSong(String path) throws FileNotFoundException, IOException, UnsupportedAudioFileException {
        addAndListenToSong(createSong(path));
    }

    /**
     * Check if playlist is correct or not
     * Test if array list of songs is empty
     * @return true if correct or false
     */
    public boolean checkPlaylist() {
        return !_mySongs.isEmpty();
    }

    /**
     * Play the active song or the first song in the playlist
     */
    public void play() {
        if (_myActiveSong == null) {
            _myActiveSong = _mySongs.get(0);
            setIndex(0);
        }

        try {
            _myActiveSong.start();
        } catch (IllegalThreadStateException ex) {
        }

        _myActiveSong.play();
        _myModel.setState("play");
    }

    /**
     * Toogle to pause the active song
     */
    public void pause() {
        _myActiveSong.pause();
        _myModel.setState("pause");
    }

    /**
     * 
     */
    public void restart() throws UnsupportedAudioFileException, IOException {
        _myActiveSong.restart();
        play();
    }

    /**
     * Restart the song or if song is not begin start the previous
     */
    public void previous() throws UnsupportedAudioFileException, IOException {

        stop();

        if (_indexSong <= 0) {

            if (!isRepeat()) {
                return;
            }
            setIndex(_mySongs.size() - 1);


        } else {
            changeIndex(-1);
        }

        System.err.println("Try to get previous song --> n° " + _indexSong);

        _myActiveSong = _mySongs.get(_myOrder.get(_indexSong));
        restart();
    }

    /**
     * Start the next song if exist or stop anything
     * TODO Prévoir un mode aléatoire qui ne choisit pas la prochaine chanson de la liste
     */
    public void next() throws UnsupportedAudioFileException, IOException {

        stop();

        // If songs list is ended, we stop everything
        if (_indexSong >= _mySongs.size() - 1) {

            if (!_isRepeat) {
                return;
            }
            setIndex(0);

        } else {
            changeIndex(1);
        }

        System.err.println("Try to get next song --> n° " + _indexSong);

        _myActiveSong = _mySongs.get(_myOrder.get(_indexSong));
        restart();
    }

    /**
     * Unload the active song if exist and set to null concerned variable
     */
    public void stop() {
        if (_myActiveSong != null) {
            _myActiveSong.turnOff();
            try {
                _myActiveSong.restart();
            } catch (UnsupportedAudioFileException ex) {
            } catch (IOException ex) {
            }
        }
        _myActiveSong = null;
        _myModel.setState("stop");
    }

    /**
     * Destroy all songs of the current playlist
     */
    public void destroy() {
        stop();
        for (IAudioSongController song : _mySongs) {
            song.turnOff();
        }
        _mySongs = null;
    }
    
    /**
     * Called by AudioSongController when a song is finish
     */
    public void endOfSong() {
        try {
            next();
        } catch (UnsupportedAudioFileException ex) {
            Logger.getLogger(AudioPlaylistController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(AudioPlaylistController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * @return the _isShuffle
     */
    public boolean isShuffle() {
        return _isShuffle;
    }

    /**
     * @param isShuffle the _isShuffle to set
     */
    public void isShuffle(boolean isShuffle) {
        _isShuffle = isShuffle;

        if (_isShuffle) {
            Collections.shuffle(_myOrder);
        } else {
            Collections.sort(_myOrder);
        }
    }

    /**
     * @return the _isRepeat
     */
    public boolean isRepeat() {
        return _isRepeat;
    }

    /**
     * @param isRepeat the _isRepeat to set
     */
    public void isRepeat(boolean isRepeat) {
        _isRepeat = isRepeat;
    }
}
